package usecase;

import IBO.ICodePostal;
import IBO.IEmployeInterne;
import IBO.IIntervention;
import IBO.ITechnicien;
import IBO.IZoneGeographique;
import IGUI.Subscriber;
import IUSECASE.IUC_GestionEmployes;
import bo.Adresse;
import bo.CodePostal;
import bo.EmployeInterne;
import bo.Intervention;
import bo.ListeEmployesInterne;
import bo.ListeTechniciens;
import bo.Role;
import bo.Technicien;
import bo.Zone;
import boerrors.AdresseMinimumMultiplicityException;
import boerrors.CodePostalInexistantException;
import boerrors.CodePostalMinimumMultiplicityException;
import boerrors.EmployeInexistantException;
import boerrors.LoginException;
import boerrors.RoleMinimumMultiplicityException;
import boerrors.TechnicienInexistantException;
import boerrors.ZoneInexistantException;
import boerrors.ZoneMinimumMultiplicityException;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
import java.util.GregorianCalendar;
import java.util.Vector;
import java.util.logging.Level;
import java.util.logging.Logger;
 
public class GestionEmployes extends UnicastRemoteObject implements IUC_GestionEmployes{

        private static GestionEmployes instance = null;    
   
        //*******************************************************************    
        //Constructeur du singleton    
        //*******************************************************************        

        public static GestionEmployes getInstance() throws RemoteException{        
                if(instance == null)            
                instance = new GestionEmployes();        
                return instance;    
        }
   
        public GestionEmployes() throws RemoteException{
                super();
        } 
    
        //*******************************************************************
        //Convertir objet BO en objet IBO
        //*******************************************************************
        
        //Code Postal
        private Vector<ICodePostal> convertCPtoICP(Vector<CodePostal> listeCP) throws RemoteException {
                Vector<ICodePostal> lstTmp = new Vector<ICodePostal>();
                for (int i = 0; i < listeCP.size(); i++){lstTmp.add((ICodePostal) listeCP.get(i));}
                return lstTmp;
        }
  
        //Employe interne
        private Vector<IEmployeInterne> convertEmpltoIEmpl(Vector<EmployeInterne> liste) throws RemoteException {
                Vector<IEmployeInterne> lstTmp = new Vector<IEmployeInterne>();
                for (int i = 0; i < liste.size(); i++){
                    liste.get(i).getNom();
                    lstTmp.add((IEmployeInterne) liste.get(i));}
                return lstTmp;
        }

        //Technicien
        private Vector<ITechnicien> convertTechtoITech(Vector<Technicien> liste) throws RemoteException {
                Vector<ITechnicien> lstTmp = new Vector<ITechnicien>();
                for (int i = 0; i < liste.size(); i++){
                    liste.get(i).getNom();
                    lstTmp.add((ITechnicien) liste.get(i));}
                return lstTmp;
        }
        
        //*******************************************************************    
        //Methodes heritees    
        //******************************************************************* 

        //Employe interne
        public void creerEmploye(   int matricule, String nom, String prenom, String rue, String numero, 
                                    String[] codePostal, String telephone, String email, Boolean[] role, 
                                    String fonction, String password) throws RemoteException {
                try {
                    CodePostal cp = CodePostal.rechercherCodePostal(codePostal[1], codePostal[2]);
                    Adresse adresse = new Adresse(rue, numero, cp);
                    Role employeRole = new Role(role[0], role[1], role[2], role[3], role[4], role[5]);
                    new EmployeInterne(matricule, nom, prenom, adresse, telephone, email, employeRole, fonction, password);
                } catch (CodePostalInexistantException ex) {
                    Logger.getLogger(GestionEmployes.class.getName()).log(Level.SEVERE, null, ex);
                }
        }
        
        public void modifierEmploye(int matricule, String nom, String prenom, String rue, String numero, String codePostal, 
                                    String commune, String telephone, String email, Boolean[] role, String password)
                                    throws RemoteException {
                try {
                    //On recupere l'employe en fonction de son matricule
                    EmployeInterne employe = bo.ListeEmployesInterne.getInstance().rechercherEmploye(matricule);
                    EmployeInterne clone = (EmployeInterne) employe.clone();
                    //On definit les attributs du clone
                    clone.setNom(nom);
                    clone.setPrenom(prenom);
                    clone.setTelephone(telephone);
                    clone.setEmail(email);
                    clone.getAdresse().setIdAdresse(employe.getAdresse().getIdAdresse());
                    clone.getAdresse().setRue(rue);
                    clone.getAdresse().setNumero(numero);
                    clone.getAdresse().enregistrerCodePostalClone(CodePostal.rechercherCodePostal(codePostal, commune));
                    clone.enregistrerRoleClone(new Role(role[0], role[1], role[2], role[3], role[4], role[5]));
                    clone.setPassword(password);
                            //On insere les valeurs du clone dans la DB
                    bo.EmployeInterne.modifier(clone);
                    //L'insertion c'est passee correctement
                    //On reassigne les valeurs du clone au client.
                    employe.setNom(clone.getNom());
                    employe.setPrenom(clone.getPrenom());
                    employe.setTelephone(clone.getTelephone());
                    employe.setEmail(clone.getEmail());
                    employe.getAdresse().setIdAdresse(clone.getAdresse().getIdAdresse());
                    employe.getAdresse().setRue(clone.getAdresse().getRue());
                    employe.getAdresse().setNumero(clone.getAdresse().getNumero());
                    employe.getAdresse().enregistrerCodePostalClone(clone.getAdresse().getCodePostal());
                    employe.enregistrerRoleClone(new Role(role[0], role[1], role[2], role[3], role[4], role[5]));
                    employe.setPassword(password);
                        } catch (CodePostalMinimumMultiplicityException ex) {
                    Logger.getLogger(GestionEmployes.class.getName()).log(Level.SEVERE, null, ex);
                } catch (CodePostalInexistantException ex) {
                    Logger.getLogger(GestionEmployes.class.getName()).log(Level.SEVERE, null, ex);
                } catch (AdresseMinimumMultiplicityException ex) {
                    Logger.getLogger(GestionEmployes.class.getName()).log(Level.SEVERE, null, ex);
                } catch (EmployeInexistantException ex) {
                    Logger.getLogger(GestionEmployes.class.getName()).log(Level.SEVERE, null, ex);
                }
        }
        
        public Vector<IEmployeInterne> listerEmployes()throws RemoteException {
                Vector<IEmployeInterne> listeTmp = convertEmpltoIEmpl(bo.ListeEmployesInterne.getInstance().getListeEmployeInterne());
                return listeTmp;
        }

        public Vector<IEmployeInterne> rechercherEmploye(int matricule) throws RemoteException {
                try {
                    Vector<IEmployeInterne> lstEmploye = new Vector<IEmployeInterne>();
                    EmployeInterne emplTmp = bo.ListeEmployesInterne.getInstance().rechercherEmploye(matricule);
                    lstEmploye.add(emplTmp);
                    return lstEmploye;
                } catch (EmployeInexistantException ex) {
                    Logger.getLogger(GestionEmployes.class.getName()).log(Level.SEVERE, null, ex);
                    return null;
                }
        }
    
        public Vector<IEmployeInterne> rechercherEmploye(String nom, String prenom) throws RemoteException {
                Vector<IEmployeInterne> lstEmploye = new Vector<IEmployeInterne>();
                Vector<EmployeInterne> lstTmp = bo.ListeEmployesInterne.getInstance().rechercherEmployeInterne(nom, prenom);
                    for (int i = 0 ; i < lstTmp.size() ; i++) lstEmploye.add((IEmployeInterne) lstTmp.get(i));
                return lstEmploye;
        }
        
        public IEmployeInterne loginEmployeInterne(int matricule, String password) throws RemoteException {
                try {
                    IEmployeInterne employe;
                    employe = bo.ListeEmployesInterne.getInstance().rechercherEmploye(matricule);
                    if (employe.getPassword().compareTo(password) == 0) {
                        return employe;
                    }
                    throw new LoginException();
                } catch (LoginException ex) {
                    Logger.getLogger(GestionEmployes.class.getName()).log(Level.SEVERE, null, ex);
                    return null;
                } catch (EmployeInexistantException ex) {
                    Logger.getLogger(GestionEmployes.class.getName()).log(Level.SEVERE, null, ex);
                    return null;
                }
        } 
   
        //Technicien
        public void creerTechnicien(int matricule, String nom, String prenom, String rue, String numero, 
                                    String[] codePostal, String telephone, String email, Boolean[] role, 
                                    String fonction, String password, IZoneGeographique zone) throws RemoteException {
                try {
                    CodePostal cp = CodePostal.rechercherCodePostal(codePostal[1], codePostal[2]);
                    Adresse adresse = new Adresse(rue, numero, cp);
                    Role employeRole = new Role(role[0], role[1], role[2], role[3], role[4], role[5]);
                    Zone zoneTechnicien = new Zone(zone.getIdZone(), zone.getLibelleZone());
                    new Technicien(matricule, nom, prenom, adresse, telephone, email, employeRole, fonction, password, zoneTechnicien);
                } catch (CodePostalInexistantException ex) {
                    Logger.getLogger(GestionEmployes.class.getName()).log(Level.SEVERE, null, ex);
                }
        }
        
        public void modifierTechnicien( int matricule, String nom, String prenom, String rue, String numero, String codePostal, 
                                        String commune, String telephone, String email, Boolean[] role, String password, 
                                        IZoneGeographique zone) 
                                        throws RemoteException {
                try {
                    Technicien technicien = bo.ListeTechniciens.getInstance().rechercherEmploye(matricule);

                    Technicien clone = (Technicien) technicien.clone();
                    //On definit les attributs du clone
                    clone.setNom(nom);
                    clone.setPrenom(prenom);
                    clone.setTelephone(telephone);
                    clone.setEmail(email);
                    clone.getAdresse().setIdAdresse(technicien.getAdresse().getIdAdresse());
                    clone.getAdresse().setRue(rue);
                    clone.getAdresse().setNumero(numero);
                    clone.getAdresse().enregistrerCodePostal(CodePostal.rechercherCodePostal(codePostal, commune));
                    clone.enregistrerRoleClone(new Role(role[0], role[1], role[2], role[3], role[4], role[5]));
                    clone.setPassword(password);
                    clone.enregistrerZoneClone(new Zone(((IZoneGeographique)zone).getIdZone(), ((IZoneGeographique)zone).getLibelleZone()));
                    //On insere les valeurs du clone dans la DB
                    bo.Technicien.modifier(clone);
                    //On reassigne les valeurs du clone au technicien.
                    technicien.setNom(clone.getNom());
                    technicien.setPrenom(clone.getPrenom());
                    technicien.setTelephone(clone.getTelephone());
                    technicien.setEmail(clone.getEmail());
                    technicien.getAdresse().setIdAdresse(clone.getAdresse().getIdAdresse());
                    technicien.getAdresse().setRue(clone.getAdresse().getRue());
                    technicien.getAdresse().setNumero(clone.getAdresse().getNumero());
                    technicien.getAdresse().enregistrerCodePostal(clone.getAdresse().getCodePostal());
                    technicien.enregistrerRoleClone(new Role(role[0], role[1], role[2], role[3], role[4], role[5]));
                    technicien.setPassword(password);
                    technicien.enregistrerZoneClone(clone.getZone());
                } catch (CodePostalInexistantException ex) {
                    Logger.getLogger(GestionEmployes.class.getName()).log(Level.SEVERE, null, ex);
                } catch (TechnicienInexistantException ex) {
                    Logger.getLogger(GestionEmployes.class.getName()).log(Level.SEVERE, null, ex);
                } catch (RoleMinimumMultiplicityException ex) {
                    Logger.getLogger(GestionEmployes.class.getName()).log(Level.SEVERE, null, ex);
                } catch (ZoneMinimumMultiplicityException ex) {
                    Logger.getLogger(GestionEmployes.class.getName()).log(Level.SEVERE, null, ex);
                } catch (AdresseMinimumMultiplicityException ex) {
                    Logger.getLogger(GestionEmployes.class.getName()).log(Level.SEVERE, null, ex);
                } catch (CodePostalMinimumMultiplicityException ex) {
                    Logger.getLogger(GestionEmployes.class.getName()).log(Level.SEVERE, null, ex);
                }
        }
    
        public Vector<ITechnicien> listerTechniciens()throws RemoteException {
                    Vector<ITechnicien> listeTmp = convertTechtoITech(bo.ListeTechniciens.getInstance().getListeTechnicien());
                    return listeTmp;
        }

        public Vector<ITechnicien> rechercherTechnicien(int matricule) throws RemoteException {
                Vector<ITechnicien> lstTechnicien = new Vector<ITechnicien>();
                Technicien techTmp = bo.ListeTechniciens.getInstance().rechercherEmploye(matricule);
                lstTechnicien.add(techTmp);
                return lstTechnicien;
        }
    
        public Vector<ITechnicien> rechercherTechnicien(String nom, String prenom) throws RemoteException {
                Vector<ITechnicien> lstTechnicien = new Vector<ITechnicien>();
                Vector<Technicien> lstTmp = bo.ListeTechniciens.getInstance().rechercherTechnicien(nom, prenom);
                for (int i = 0 ; i < lstTmp.size() ; i++) lstTechnicien.add((ITechnicien) lstTmp.get(i));
                return lstTechnicien;
        }
    
        public Vector<IIntervention> listerIntervention(ITechnicien technicien) throws RemoteException {
                Vector<Intervention> lstIntervention = new Vector<Intervention>();
                Vector<IIntervention> lstIIntervention = new Vector<IIntervention>();
                Technicien techTmp = bo.ListeTechniciens.getInstance().rechercherEmploye(technicien.getMatricule());
                lstIntervention = techTmp.getListeInterventions();
                    for (int i = 0 ; i < lstIntervention.size() ; i++) lstIIntervention.add((IIntervention) lstIntervention.get(i));
                return lstIIntervention;
        }
        
        public Vector<IIntervention> listerIntervention(ITechnicien technicien, GregorianCalendar dateIntervention) throws RemoteException {
                Vector<Intervention> lstIntervention = new Vector<Intervention>();
                Vector<IIntervention> lstIIntervention = new Vector<IIntervention>();
                Technicien techTmp = bo.ListeTechniciens.getInstance().rechercherEmploye(technicien.getMatricule());
                lstIntervention = techTmp.getListeInterventions();
                    for (int i = 0 ; i < lstIntervention.size() ; i++) {
                        if (lstIntervention.get(i).getDateIntervention()==dateIntervention)
                        lstIIntervention.add((IIntervention) lstIntervention.get(i));
                    }
                return lstIIntervention;
        }
        
        public Vector<IZoneGeographique> listerZone() throws RemoteException {
                try {
                    return bo.Zone.lister();
                } catch (ZoneInexistantException ex) {
                    Logger.getLogger(GestionEmployes.class.getName()).log(Level.SEVERE, null, ex);
                        return null;
                }
        }
    
        public ITechnicien loginTechnicien(int matricule, String password) throws RemoteException {
                try {
                    ITechnicien technicien;
                    technicien = bo.ListeTechniciens.getInstance().rechercherEmploye(matricule);
                    if (technicien.getPassword().compareTo(password) == 0) {
                        return technicien;
                    }
                    throw new LoginException();
                } catch (LoginException ex) {
                    Logger.getLogger(GestionEmployes.class.getName()).log(Level.SEVERE, null, ex);
                    return null;
                }
        }

        //Employe
        public Vector<ICodePostal> rechercherCP(String codePostal) throws RemoteException {
                try {
                    return convertCPtoICP(bo.CodePostal.listerCodePostaux(codePostal));
                } catch (Exception ex) {
                    Logger.getLogger(GestionEmployes.class.getName()).log(Level.SEVERE, null, ex);
                    return null;
                }
        }

        public Vector<ICodePostal> rechercherCommune(String commune) throws RemoteException {
                try {
                    return convertCPtoICP(bo.CodePostal.listerCodePostaux(commune));
                } catch (Exception ex) {
                    Logger.getLogger(GestionEmployes.class.getName()).log(Level.SEVERE, null, ex);
                    return null;
                }
        }
        
        //*******************************************************************    
        //MVC    
        //*******************************************************************        
        
        public void subscribingListeTechniciens(Subscriber subscriber) throws RemoteException{
            ListeTechniciens.getInstance().subscribe(subscriber);
        }
        
        public void unSubscribingListeTechniciens(Subscriber subscriber) throws RemoteException{
            ListeTechniciens.getInstance().unsubscribe(subscriber);
        }   

        public void subscribingListeEmployesInt(Subscriber subscriber) throws RemoteException{
            ListeEmployesInterne.getInstance().subscribe(subscriber);
        }
        
        public void unSubscribingListeEmployesInt(Subscriber subscriber) throws RemoteException{
            ListeEmployesInterne.getInstance().unsubscribe(subscriber);
        }        
        
}